package questions;

import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author: Administrator
 * @Date: 2023/5/9 10:09
 *
 * 先添加命令行参数：
 * ···下行开始
   "你好 {{ name }}. 年华 {{ age }}.  {{{{facade}}}}"
   " { \"age\": 21,\"name\":\"nick\",\"facade\":\"deepKey\",\"deepKey\":\"deepProcessed\"}"
 * ···上行结束
 *
 *
 */

public class StringPattern {

    public static void main(String[] args) {
        if (args == null || args.length < 2)
            throw new IllegalArgumentException("缺参数.");
        String input = args[0];
        Map<String, Object> parse = (Map<String, Object>) JSON.parse(args[1]);

        System.out.println(StringPlaceHolder.process(input, parse));
        System.out.println(StringPlaceHolder2.deepProcess(input, parse));
//        long start1 = System.currentTimeMillis();
        System.out.println(StringPlaceHolder2.process(input, parse));
//        long l2 = System.currentTimeMillis();

//        long l3 = System.currentTimeMillis();
//        System.out.println((l3 - l2) + " " + (l2 - start1));

    }

    /**
     * @see StringPlaceHolder#loopReplace 方法存在处理漏洞，且可以优化
     * 优化版参见： {@link StringPlaceHolder2#deepProcess(java.lang.String, java.util.Map) }
     * <p>
     * 漏洞： {{{{name}}}}  {"name":"mock","mock":250}  可能会处理成  250、 存在先后问题
     * 可优化：replace使用了 {@link java.lang.String#replace(java.lang.CharSequence, java.lang.CharSequence)}
     * 此方法会重复compile,重复replaceAll
     */
    @Deprecated
    static class StringPlaceHolder {
        private static final String PATTERN_STRING = "\\{\\{(\\s*\\w+)?\\s*\\}\\}";
        private static final Pattern pattern = Pattern.compile(PATTERN_STRING);

        private static Matcher match(String target) {

            return pattern.matcher(target);
        }

        public static String process(String content, Map<String, Object> values) {
            List<String> ori = new ArrayList<>();
            List<String> keys = new ArrayList<>();
            Matcher matcher = match(content);
            while (matcher.find()) {
                String group0 = matcher.group();
                String group1 = matcher.group(1);
                if (group1 == null || group1.trim().length() == 0) {
                    continue;
                }
                ori.add(group0);
                keys.add(group1.trim());
            }
            if (!values.keySet().containsAll(keys)) {
                Set<String> strings = values.keySet();
                keys.removeAll(strings);
                throw new IllegalArgumentException(keys  + " 没有");
            }

            return loopReplace(content, values, ori, keys);
        }

        private static String loopReplace(String input, Map<String, Object> givenValues, List<String> ori, List<String> keys) {
            for (int i = 0; i < ori.size(); i++) {
                input = input.replace(ori.get(i), givenValues.get(keys.get(i)).toString());
            }
            return input;
        }

    }

    static class StringPlaceHolder2 {
        private static final String PATTERN_STRING = "\\{\\{(\\s*\\w+)?\\s*\\}\\}";
        private static final Pattern pattern = Pattern.compile(PATTERN_STRING);

        private static Matcher match(String target) {

            return pattern.matcher(target);
        }

        public static String process(String content, Map<String, Object> values) {
            Matcher matcher = match(content);
            StringBuffer stringBuffer = new StringBuffer();
            while (matcher.find()) {
                String group1 = matcher.group(1);
                if (group1 == null || group1.trim().length() == 0) {
                    continue;
                }
                if (!values.containsKey(group1.trim())) {
                    throw new IllegalArgumentException("\"" + group1.trim() + "\"" + " 没有.");
                }
                matcher.appendReplacement(stringBuffer, values.get(group1.trim()).toString());

            }
            matcher.appendTail(stringBuffer);
            return stringBuffer.toString();
        }

        public static String deepProcess(String content, Map<String, Object> values) {
            Boolean changed = false;
            do {
                String res = process(content, values);
                changed = !content.equals(res);
                content = res;
            } while (changed);

            return content;
        }


    }

}

